﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Cofe.Core.Logger;

namespace Cofe.Web.Feed
{
    public abstract class FeedBuilderBase<T> : IFeedBuilder<T>
        where T : EventArgs
    {
        protected IFeedService<T> _feedService;
        protected string ServiceName = "Unnamed Builder";
        protected string Title = "Title";

        public FeedBuilderBase(IFeedService<T> feedService)
        {
            _feedService = feedService;
        }

        public Feed<T> LoadRecentEventsFeed(string fileName)
        {
            if (!_feedService.FileSystem.IsExists(FeedDirectory.Current, fileName))
                return null;

            using (XmlReader reader = _feedService.FileSystem.GetXmlReader(FeedDirectory.Current, fileName))
            {
                SyndicationFeed feed = SyndicationFeed.Load(reader);
                FeedId feedId = FeedId.FromUrl(feed.GetViaLink().Uri, fileName, this);
                return new Feed<T>(feedId, feed, this);
            }
        }

        public Feed<T> CreateRecentEventsFeed(FeedId feedId, FeedId previosFeedId)
        {
            SyndicationFeed feed = new SyndicationFeed
            {
                Id = new UniqueId(Guid.NewGuid()).ToString(),
                Title = SyndicationContent.CreatePlaintextContent(Title),
                Generator = ServiceName,
                LastUpdatedTime = DateTime.Now,
                Items = new List<SyndicationItem>()
            };

            feed.Authors.Add(new SyndicationPerson { Name = ServiceName });

            feed.Links.Add(_feedService.Links.CreateFeedLink(LinkType.self, feedId));
            feed.Links.Add(_feedService.Links.CreateFeedLink(LinkType.via, feedId));
            if (previosFeedId != null)
                feed.Links.Add(_feedService.Links.CreateFeedLink(LinkType.prevArchive, previosFeedId));

            return new Feed<T>(feedId, feed, this);
        }

        public Feed<T> CreateNextFeed(FeedId feedId)
        {
            return CreateRecentEventsFeed(feedId.Next(), feedId);
        }

        public Feed<T> CreateArchiveFeed(Feed<T> feed, FeedId currentFeedId, FeedId nextFeedId)
        {
            SyndicationFeed archive = feed.InnerFeed.Clone(true);

            archive.GetSelfLink().Uri = archive.GetViaLink().Uri;
            archive.Links.Remove(archive.GetViaLink());
            archive.Links.Add(_feedService.Links.CreateFeedLink(LinkType.nextArchive, nextFeedId));
            archive.ElementExtensions.Add(new SyndicationElementExtension("archive", "http://purl.org/syndication/history/1.0", string.Empty));

            return new Feed<T>(currentFeedId.ToArchive(), archive, this);
        }

        public abstract FeedEntry<T> BuildEntry(IEventLog<T> eventLog);

        public UriTemplate FeedTemplate { get; set; }
        public UriTemplate EventTemplate { get; set; }
        public UriTemplate EntryTemplate { get; set; }
    }
}
